#include "stateMonitorWidget.h"
#include "ui_stateMonitorWidget.h"
#include "BRE_EEG_dataStruct.h"
#include "ConfigImport.h"


#include <QMessageBox>
#include <QPainter>
#include <QLabel>
#include <QCloseEvent>
#include <QWidget>
#include <QObject>
#include <iostream>
#include <QMovie>
#include <QScreen>
#include <QRect>
#include <QSpinBox>

/* ====== StateMonitorWidget =========  */
StateMonitorWidget::StateMonitorWidget(const QMap<int, QString> &electrodeMap, QWidget *parent) :
    electrodeNameMap(electrodeMap),
    orgData_beforeFilter(ConfigImport::getInstance()->channalNum),
    QWidget(parent),
    // 大系统的滤波
    // emotionfilter(ConfigImport::getInstance()->getMapVal("EmotionFilterPara")),
    emotionfilter(1000, 20.0, 75.0, ConfigImport::getInstance()->channalNum),
    ui(new Ui::StateMonitorWidget)
{
    ui->setupUi(this);
    Wave_filterFlag = ui->btn_filterSW->isChecked();

    QHash<QString, QLabel*> labelHash;
    // labelHash.insert("emo_negLabel", ui->emo_negLabel);
    labelHash.insert("emo_neuLabel", ui->emo_neuLabel);
    // labelHash.insert("emo_posLabel", ui->emo_posLabel);
    labelHash.insert("y_negLabel", ui->y_negLabel);
    labelHash.insert("y_neuLabel", ui->y_neuLabel);
    labelHash.insert("y_posLabel", ui->y_posLabel);
    // printf("hash:%lld,ui:%lld\n",labelHash.value("y_neuLabel"),ui->y_neuLabel);

    // 情绪动态显示窗口初始化
    emotionInf = new EmotionInterface(labelHash, ui->emo_plot);
    // 脑网络显示窗口初始化
    networkInf = new NetworkInterface(ui->networkPlot);
    // 波形窗口初始化
    // std::cout << "ConfigImport::getInstance()->channalNum=" << static_cast<int>(ConfigImport::getInstance()->channalNum) << std::endl;
    if(ConfigImport::getInstance()->use_simulationDev()){
        ui->ratioSpBox->setValue(1);
        ui->offsetSpBox->setValue(100);
        ui->scaleSpBox->setValue(1000);
    }
    waveInf = new WavePlotInterface(ui->wave_plot, ConfigImport::getInstance()->channalNum, 
                                        ui->ratioSpBox->value(), ui->offsetSpBox->value(), ui->scaleSpBox->value());
    
    // 通道目录初始化
    treeDirInf = new TreeDirectoryInterface(ui->TreeDirectoryWidget, *waveInf, electrodeNameMap);

    // ui->netWorkPlot_widget->setStyleSheet("background-color: #e5f9ff; border-radius: 10px;");
    // ui->netWorkPlot_widget->setStyleSheet(
    //     "background-color: #e5f9ff; "
    //     "border-radius: 20px; "
    //     "margin: 5px;" // 添加适当的边距
    // );
    // ui->expression_widget->setStyleSheet(
    //     "background-color: #e5f9ff; "
    //     "border-radius: 20px; "
    //     "margin: 5px;" // 添加适当的边距
    // );
    // ui->emoPlot_widget->setStyleSheet(
    //     "background-color: #e5f9ff; "
    //     "border-radius: 20px; "
    //     "margin: 5px;" // 添加适当的边距
    // );


    // 获取主屏幕的信息
    QScreen *screen = QApplication::primaryScreen();
    QRect screenGeometry = screen->geometry();

    // 计算窗口的位置和大小，使其充满屏幕左边
    // int windowWidth = screenGeometry.width() / 2 - 72; // 窗口宽度为屏幕宽度的一半
    int windowWidth = screenGeometry.width() / 2; // 窗口宽度为屏幕宽度的一半
    int windowHeight = screenGeometry.height(); // 窗口高度为屏幕高度
    int windowX = 0; // 窗口的X位置（左半部分）
    int windowY = 0; // 窗口的Y位置（顶部）

    // 设置窗口的位置和大小
    // this->setWindowFlags(Qt::FramelessWindowHint); // 隐藏顶部状态栏
    this->setGeometry(windowX, windowY, windowWidth, windowHeight);

    // connect(ui->ratioSpBox, SIGNAL(editingFinished(double)), waveInf, 
    //         SLOT(amplitudeRatioUpdate(double)));
    // connect(ui->offsetSpBox, SIGNAL(editingFinished(double)), waveInf, 
    //         SLOT(amplitudeOffsetUpdate(double)));

    connect(ui->ratioSpBox, &QSpinBox::editingFinished, this, [=]{
        waveInf->amplitudeRatioUpdate(ui->ratioSpBox->value());
    });

    connect(ui->offsetSpBox, &QSpinBox::editingFinished, this, [=]{
        waveInf->amplitudeOffsetUpdate(ui->offsetSpBox->value());
    });

    connect(ui->scaleSpBox, &QSpinBox::editingFinished, this, [=]{
        waveInf->timeScaleUpdate(ui->scaleSpBox->value());
    });
}

StateMonitorWidget::~StateMonitorWidget(){
    delete emotionInf;
    delete networkInf;
    delete waveInf;
    delete treeDirInf;
    // std::cout << "~StateMonitorWidget()" << std::endl;
    delete ui;

}

// emotionInf

EmotionInterface::EmoMode StateMonitorWidget::getCurrentEmotion() const {return emotionInf->currentEmotion;}
EmotionInterface::EmoMode StateMonitorWidget::getVideoEmotion() const {return emotionInf->videoEmotion;}

void StateMonitorWidget::set_emoGIF(){emotionInf->set_emoGIF();}
void StateMonitorWidget::hideEmoGIF(){emotionInf->hideEmoGIF();}

void StateMonitorWidget::setCurrent_emotion(EmotionInterface::EmoMode mode){emotionInf->setCurrent_emotion(mode);}
void StateMonitorWidget::setCurrent_emotion(int mode){
    emotionInf->setCurrent_emotion(static_cast<EmotionInterface::EmoMode>(mode));
}
void StateMonitorWidget::setVideo_emotion(EmotionInterface::EmoMode mode){emotionInf->setVideo_emotion(mode);}
void StateMonitorWidget::setGraph_visible(int graphID, bool flag){emotionInf->setGraph_visible(graphID, flag);}
void StateMonitorWidget::emoLabel_startPlot(){emotionInf->startPlot();}
void StateMonitorWidget::emoLabel_stopPlot(){emotionInf->stopPlot();}
void StateMonitorWidget::emoLabel_clearPlot(){emotionInf->clearPlot();}

// waveInf
void StateMonitorWidget::plotDataUpdate(const GenEEGData& data){
    
    
    // 椭圆滤波
    // 参数默认，默认带有缓存
    // EmotionFilter emotionfilter = EmotionFilter();


    if(Wave_filterFlag){
        // std::cout << "filter" << std::endl;
filter: GenEEGData filterData(ConfigImport::getInstance()->channalNum);
        int res;

#ifdef FILT_TIME
        auto BT_filt = std::chrono::steady_clock::now();
#endif
        for(auto &it:data.data){
            orgData_beforeFilter.data.push_back(it);
            filterData.data.push_back(it);
        }
        
        // if(orgData_beforeFilter.data.size() >= 302){
            // res = emotionfilter.filt(orgData_beforeFilter, filterData);
            // res = emotionfilter.ellipticFilt(orgData_beforeFilter, filterData);
            res = emotionfilter.butterworthFilt(orgData_beforeFilter, filterData, 1);
            // 滤波成功
            if(!res){
                // std::cout << "filterPoint:" << orgData_beforeFilter.data.size() << std::endl;
                orgData_beforeFilter.data.clear();
                waveInf->addData(filterData);
                for(auto &it : filterData.data){
                    filtData_acc.data.push_back(it);
                }
#ifdef FILT_TIME
                auto AT_filt = std::chrono::steady_clock::now();
                double duration_millsecond = std::chrono::duration<double, std::milli>(AT_filt - BT_filt).count();
                std::cout << "pre cycle:" << duration_millsecond << "ms" << std::endl;
#endif
            }
        // }
        
    }
    else{
        // std::cout << "un filter" << std::endl;
        if(!orgData_beforeFilter.data.empty()){
            std::cout << "filter remainning data." << std::endl;
            goto filter;
        }
        waveInf->addData(data);
    }
}

void StateMonitorWidget::receive_network(const arma::rowvec &data){
    networkInf->set_networkData(data);
}

void StateMonitorWidget::networkPlot(){
    networkInf->clear();
    networkInf->networkCreate();
    networkInf->networkReplot();
}

void StateMonitorWidget::networkPlot_test(){
    networkInf->clear();
    // while(1){
        int count = qrand()%25 + 10;
        for(int i=0; i<count; ++i){
            networkInf->add_line(EEGDEV::electrode_coordinate[qrand()%64], 
                            EEGDEV::electrode_coordinate[qrand()%64]);
        }
    // }
    networkInf->networkReplot();
}

void StateMonitorWidget::waveStopPlot(){
    waveInf->stopPlot();
}

void StateMonitorWidget::closeEvent(QCloseEvent *event)
{
    emit widgetClose(WINID::StateMonitorWidget);
    std::cout << "stateMonitor Windows is closed!" << std::endl;
    // saveEEGData("../bin/EEGData.bin", program.org_eegData, true);


}

void StateMonitorWidget::on_btn_clearWave_clicked(bool checked){
    waveInf->clearAll();
}

void StateMonitorWidget::on_btn_filterSW_clicked(bool checked){
    Wave_filterFlag = ui->btn_filterSW->isChecked();
}
